package com.mojito.learn.design.patterns;

import java.util.ArrayList;
import java.util.EventListener;
import java.util.List;

/**
 * 观察者模式
 * <p>
 * 在对象之间定义一对多的依赖, 这样一来, 当一个对象改变状态, 依赖它的对象都会收到通知, 并自动更新。
 * <p>
 * 使用场景：
 * * {@link java.util.Observer}
 * * {@link EventListener}
 * * RxJava
 *
 * @author liufq
 * @since 2022/1/24 下午5:35
 */
public class ObserverPattern {

    public static void main(String[] args) {
        Observed observed = new ObservedImpl();
        observed.addObserver(new Observer0());
        observed.addObserver(new Observer1());

        // 被观察者更新数据的时候会自动去通知观察者，执行响应的逻辑
        observed.update("2022-01-24 天气晴");
        observed.update("2022-01-25 天气雨");
    }

    /**
     * 0号观察者
     */
    static class Observer0 implements Observer {

        @Override
        public void callback(String weather) {
            System.out.println("0号观察者天气：" + weather);
        }
    }

    /**
     * 1号观察者
     */
    static class Observer1 implements Observer {

        @Override
        public void callback(String weather) {
            System.out.println("1号观察者天气：" + weather);
        }
    }

    /**
     * 观察者
     */
    interface Observer {

        /**
         * 被观察者发生变化回调
         */
        void callback(String weather);
    }

    /**
     * 被观察者
     */
    static class ObservedImpl implements Observed {

        private List<Observer> observers;
        private String weather;

        ObservedImpl() {
            this.observers = new ArrayList<>();
        }

        @Override
        public void addObserver(Observer observer) {
            this.observers.add(observer);
        }

        @Override
        public void update(String weather) {
            this.weather = weather;
            this.notification();
        }

        @Override
        public void notification() {
            observers.forEach(o -> o.callback(weather));
        }
    }

    interface Observed {

        /**
         * 增加观察者
         */
        void addObserver(Observer observer);

        /**
         * 被观察者更新数据
         */
        void update(String weather);

        /**
         * 通知所有观察者
         */
        void notification();
    }
}
